/*
  +----------------------------------------------------------------------+
  | PHP Version 4                                                        |
  +----------------------------------------------------------------------+
  | Copyright (c) 1997-2003 The PHP Group                                |
  +----------------------------------------------------------------------+
  | This source file is subject to version 2.02 of the PHP license,      |
  | that is bundled with this package in the file LICENSE, and is        |
  | available at through the world-wide-web at                           |
  | http://www.php.net/license/2_02.txt.                                 |
  | If you did not receive a copy of the PHP license and are unable to   |
  | obtain it through the world-wide-web, please send a note to          |
  | license@php.net so we can mail you a copy immediately.               |
  +----------------------------------------------------------------------+
  | Author: Martins Lazdans <martins@lazdans.lv>                         |
  +----------------------------------------------------------------------+

  $Id: header,v 1.10.8.1 2003/07/14 15:59:18 sniper Exp $ 
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <ip2c.h>
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_ip2c.h"

/* If you declare any globals in php_ip2c.h uncomment this:
*/
ZEND_DECLARE_MODULE_GLOBALS(ip2c)

/* True global resources - no need for thread safety here */
static int le_ip2c;
struct ip2c_db *db2;

/* {{{ ip2c_functions[]
 *
 * Every user visible function must have an entry in ip2c_functions[].
 */
function_entry ip2c_functions[] = {
	PHP_FE(ip2c_getcountry,	NULL)
	{NULL, NULL, NULL}	/* Must be the last line in ip2c_functions[] */
};
/* }}} */

/* {{{ ip2c_module_entry
 */
zend_module_entry ip2c_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
	STANDARD_MODULE_HEADER,
#endif
	"ip2c",
	ip2c_functions,
	PHP_MINIT(ip2c),
	PHP_MSHUTDOWN(ip2c),
	PHP_RINIT(ip2c),
	PHP_RSHUTDOWN(ip2c),
	PHP_MINFO(ip2c),
#if ZEND_MODULE_API_NO >= 20010901
	"0.1", /* Replace with version number for your extension */
#endif
	STANDARD_MODULE_PROPERTIES
};
/* }}} */

#ifdef COMPILE_DL_IP2C
ZEND_GET_MODULE(ip2c)
#endif

/* {{{ PHP_INI
 */
/* Remove comments and fill if you need to have entries in php.ini
*/
PHP_INI_BEGIN()
//	STD_PHP_INI_ENTRY("ip2c.database", "/etc/ip2c.db", PHP_INI_ALL, OnUpdateString, global_string, zend_ip2c_globals, ip2c_globals)
	PHP_INI_ENTRY("ip2c.database", IP2C_DB_PATH, PHP_INI_ALL, NULL)
PHP_INI_END()
/* }}} */

/* {{{ php_ip2c_init_globals
 */
/* Uncomment this function if you have INI entries */
static void php_ip2c_init_globals(zend_ip2c_globals *ip2c_globals)
{
	//ip2c_globals->global_value = 0;
	//	ip2c_globals->global_string = NULL;
}
/* }}} */

/* {{{ PHP_MINIT_FUNCTION
 */
PHP_MINIT_FUNCTION(ip2c)
{
	FILE *f;
	/* If you have INI entries, uncomment these lines */
	ZEND_INIT_MODULE_GLOBALS(ip2c, php_ip2c_init_globals, NULL);

	REGISTER_INI_ENTRIES();

	IP2C_G(ipdb) = (struct ip2c_db *)ip2c_db_init();
	ip2c_db_load(IP2C_G(ipdb), INI_STR("ip2c.database"));
	if(f = fopen("/tmp/ip2c.log", "a"))
	{
		fprintf(f, "Opening: %s\n", INI_STR("ip2c.database"));
		fclose(f);
	}

	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MSHUTDOWN_FUNCTION
 */
PHP_MSHUTDOWN_FUNCTION(ip2c)
{
	/* uncomment this line if you have INI entries */
	UNREGISTER_INI_ENTRIES();

	ip2c_db_free(IP2C_G(ipdb));

	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request start */
/* {{{ PHP_RINIT_FUNCTION
 */
PHP_RINIT_FUNCTION(ip2c)
{
	return SUCCESS;
}
/* }}} */

/* Remove if there's nothing to do at request end */
/* {{{ PHP_RSHUTDOWN_FUNCTION
 */
PHP_RSHUTDOWN_FUNCTION(ip2c)
{
	return SUCCESS;
}
/* }}} */

/* {{{ PHP_MINFO_FUNCTION
 */
PHP_MINFO_FUNCTION(ip2c)
{
	php_info_print_table_start();
	php_info_print_table_header(2, "ip2country support", "enabled");
	php_info_print_table_end();

	/* Remove comments if you have entries in php.ini */
	DISPLAY_INI_ENTRIES();
}
/* }}} */


/* Remove the following function when you have succesfully modified config.m4
   so that your module can be compiled into PHP, it exists only for testing
   purposes. */

/* Every user-visible function in PHP should document itself in the source */
/* {{{ proto string confirm_ip2c_compiled(string arg)
   Return a string to confirm that the module is compiled in */
PHP_FUNCTION(ip2c_getcountry)
{
	zval **ip_list, **val, val_n;
	HashPosition pos;
	int argc = ZEND_NUM_ARGS(), count = 0;
	uint ip_list_c_index = 0, r;
	ip2c_ip *ip_list_c;
	ip2c_country_code *iso_codes_c;

	// if count not eq 1
	if(argc != 1 || zend_get_parameters_ex(argc, &ip_list) == FAILURE)
	{
		WRONG_PARAM_COUNT;
	}

	// if type is not array
	if (Z_TYPE_PP(ip_list) != IS_ARRAY)
	{
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "The argument should be an array");
		return;
	}

	convert_to_array_ex(ip_list);

	// get array count
	zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(ip_list), &pos);
	while(zend_hash_get_current_data_ex(Z_ARRVAL_PP(ip_list), (void **)&val, &pos) == SUCCESS)
	{
		// skip non-scalar types
		if(Z_TYPE_PP(val) == IS_ARRAY || Z_TYPE_PP(val) == IS_OBJECT)
		{
			continue;
		}
		zend_hash_move_forward_ex(Z_ARRVAL_PP(ip_list), &pos);
		count++;
	}

	// array form ip list
	if((ip_list_c = emalloc(count * sizeof(ip2c_ip))) == NULL)
	{
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not enough memory");
		return;
	}

	// array for return iso codes
	if((iso_codes_c = malloc(count * sizeof(ip2c_country_code))) == NULL)
	{
		efree(ip_list_c);
		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not enough memory");
		return;
	}

	memset(iso_codes_c, 0, count * sizeof(ip2c_country_code));

	// collect input data
	zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(ip_list), &pos);
	while(zend_hash_get_current_data_ex(Z_ARRVAL_PP(ip_list), (void **)&val, &pos) == SUCCESS)
	{
		// skip non-scalar types
		if(Z_TYPE_PP(val) == IS_ARRAY || Z_TYPE_PP(val) == IS_OBJECT)
		{
			continue;
		}

		val_n = **val;
		zval_copy_ctor(&val_n);
		convert_scalar_to_number(&val_n TSRMLS_CC);
		convert_to_long(&val_n);
		ip_list_c[ip_list_c_index] = Z_LVAL(val_n);

		zend_hash_move_forward_ex(Z_ARRVAL_PP(ip_list), &pos);
		ip_list_c_index++;
	}

	ip2c_getcountry(IP2C_G(ipdb), ip_list_c, ip_list_c_index, iso_codes_c);

	// init return array
	array_init(return_value);

	for(r=0; r<ip_list_c_index; r++)
	{
		if(iso_codes_c[r])
			add_next_index_string(return_value, iso_codes_c[r], 1);
		else
			add_next_index_bool(return_value, 0);
	}

	efree(ip_list_c);
	free(iso_codes_c);
}
/* }}} */
/* The previous line is meant for vim and emacs, so it can correctly fold and 
   unfold functions in source code. See the corresponding marks just before 
   function definition, where the functions purpose is also documented. Please 
   follow this convention for the convenience of others editing your code.
*/


/*
 * Local variables:
 * tab-width: 4
 * c-basic-offset: 4
 * End:
 * vim600: noet sw=4 ts=4 fdm=marker
 * vim<600: noet sw=4 ts=4
 */
